package com.polaris.live.utils.zego.media

import androidx.annotation.IntDef
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import com.blankj.utilcode.util.StringUtils
import com.polaris.live.cache.CommonCache
import com.polaris.live.common.manager.CoroutineScopeManager
import com.polaris.live.common.util.StructUtils
import com.polaris.live.common.util.ToastGravity
import com.polaris.live.floating.FloatingWindowManager
import com.polaris.live.translation.R
import com.polaris.live.ui.party.music.listener.MediaPlayerPlayingListener
import im.zego.zegoexpress.constants.ZegoMediaPlayerState
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

/**
 * MediaProxy
 * @author Created by 天晴 on 2024/9/19 10:23
 * @since 1.0.0
 **/
object MediaProxy {

    private val musicList = mutableListOf<MusicBean>() //播放列表

    /**
     * 获取播放列表
     */
    fun getMusicList(): MutableList<MusicBean> {
        return musicList
    }

    fun addMusicList(list: List<MusicBean>) {
        musicList.addAll(list)
        CommonCache.saveMusicList(musicList)
        ToastGravity.showGravity(R.string.added_successfully)
        handlerMusicSizeUpdate(musicList.size)
    }

    fun rmMusicList(bean: MusicBean) {
        if (bean.id == currentMusicBean?.id) {
            stopMusic { }
            currentMusicBean = null
            currentMusicState = MusicState.UNREADY
        }
        musicList.remove(bean)
        CommonCache.saveMusicList(musicList)
        ToastGravity.showGravity(R.string.delete_successfully)
        handlerMusicSizeUpdate(musicList.size)
    }

    init {
        CommonCache.getMusicList()?.let {
            musicList.clear()
            musicList.addAll(it)
        }
    }

    private var mediaPlayer: MediaPlayerUtils? = null

    private var playType = MusicPlay.MUSIC_SINGLE  //播放类型

    private var currentMusicBean: MusicBean? = null  //当前播放的音乐

    private var currentMusicState: Int = MusicState.UNREADY  //当前状态

    private var currentMusicProgress: Long = 0  //播放进度

    private var listenerList = StructUtils.newSaleSet<MediaPlayerPlayingListener>()

    fun addListener(listener: MediaPlayerPlayingListener) {
        listenerList.add(listener)
        if (currentMusicState == MusicState.PLAYING) { //在播放状态立即回调
            currentMusicBean?.let {
                listener.switchMusic(it)
            }
        }
    }

    fun rmListener(listener: MediaPlayerPlayingListener?) {
        listenerList.remove(listener)
    }

    private fun handlerSwitchMusic(music: MusicBean) {
        listenerList.forEach {
            it.switchMusic(music)
        }
    }

    fun handlerMediaPlayerStateUpdate(
        state: ZegoMediaPlayerState,
        errorCode: Int,
    ) {
        if (errorCode != 0) {
            handlerMusicState(MusicState.FAIL)
            return
        }

        when (state) {
            ZegoMediaPlayerState.NO_PLAY -> {
            }

            ZegoMediaPlayerState.PLAYING -> {
                handlerMusicState(MusicState.PLAYING)
            }

            ZegoMediaPlayerState.PAUSING -> {
            }

            ZegoMediaPlayerState.PLAY_ENDED -> {
                handlerMusicState(MusicState.PLAY_ENDED)
                nextMusic()
            }
        }

    }

    fun handlerProgress(millisecond: Long) {
        currentMusicProgress = millisecond
        listenerList.forEach {
            it.progress(millisecond)
        }
    }

    private fun handlerVolume(volume: Int) {
        listenerList.forEach {
            it.onVolumeUpdate(volume)
        }
    }

    private fun handlerMusicSizeUpdate(size: Int) {
        listenerList.forEach {
            it.onMusicSizeUpdate(size)
        }
    }

    /**
     * 播放状态改变
     */
    private fun handlerMusicState(@MusicPlayState state: Int) {
        if (state == MusicState.FAIL) {
            ToastGravity.showGravity(StringUtils.getString(R.string.play_failed))
        }
        currentMusicState = state
        listenerList.forEach {
            it.musicState(state)
        }
    }

    private fun handlerMusicPlayType(@MusicPlayType type: Int) {
        listenerList.forEach {
            it.musicPlayType(type)
        }
    }

    fun closeMusic() {
        if (currentMusicBean != null) {
            currentMusicBean = null
            currentMusicState = MusicState.UNREADY
            stopMusic { }
            listenerList.forEach {
                it.closeMusic()
            }
        }
    }

    //生命周期管理
    private var lifecycleOwner: LifecycleOwner? = null
    fun observeMediaPlayer(lifecycleOwner: LifecycleOwner) {
        this.lifecycleOwner = lifecycleOwner
        if (mediaPlayer != null) {
//            destroy()
        } else {
            mediaPlayer = MediaPlayerUtils()
        }
        lifecycleOwner.lifecycle.addObserver(object : LifecycleEventObserver {
            override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    if (lifecycleOwner == this@MediaProxy.lifecycleOwner) {
                        if (FloatingWindowManager.isMinimize()) { //开启了小窗  只清除lifecycleOwner
                            MediaProxy.lifecycleOwner = null
                        } else {
                            destroy()
                        }
                    }
                }
            }
        })
    }

    fun destroy() {
        mediaPlayer?.destroyMediaPlayer()
        mediaPlayer = null
        currentMusicBean = null
        lifecycleOwner = null
        currentMusicState = MusicState.UNREADY
        currentMusicProgress = 0
    }

    /**
     * 下一首
     */
    private fun nextMusic() {
        when (playType) {
            MusicPlay.MUSIC_RANDOM -> {
                if (musicList.isNotEmpty()) {
                    val randomIndex = (0 until musicList.size).random()
                    val music = musicList[randomIndex]
                    startMusic(music)
                } else {
                    stopMusic { }
                }
            }

            MusicPlay.MUSIC_ORDER -> {
                val index = musicList.indexOfFirst { it.id == currentMusicBean?.id }
                val music = musicList.getOrNull(index + 1) ?: musicList.firstOrNull()
                music?.let {
                    startMusic(it)
                } ?: stopMusic { }
            }
        }

    }

    fun startMusic(music: MusicBean) {
        if (music.id != currentMusicBean?.id) {
            retryMusic(music)
        } else {
            when (currentMusicState) {
                MusicState.PLAY_ENDED,
                MusicState.STOPING,
                MusicState.FAIL,
                    -> {
                    retryMusic(music)
                }

                MusicState.PAUSE -> {
                    handlerMusicState(MusicState.PLAYING)
                    mediaPlayer?.resume()
                }
            }

        }
    }

    /**
     * 重新加载重试
     */
    fun retryMusic(music: MusicBean) {
        currentMusicProgress = 0
        if (currentMusicBean != null) {
            stopMusic {
                start(music)
            }
        } else {
            start(music)
        }

    }

    private fun start(music: MusicBean) {
        currentMusicBean = music
        handlerSwitchMusic(music)
        handlerMusicState(MusicState.UNREADY)
        mediaPlayer?.loadResource(music.path, success = {
            handlerMusicState(MusicState.READY)
            mediaPlayer?.enableRepeat(playType == MusicPlay.MUSIC_SINGLE)
            mediaPlayer?.start()
        }, fail = {
            handlerMusicState(MusicState.FAIL)
            ToastGravity.showGravity(R.string.play_failed)
        })
    }

    /**
     *  暂停播放
     */
    fun pause() {
        handlerMusicState(MusicState.PAUSE)
        mediaPlayer?.pause();
    }

    fun stopMusic(success: () -> Unit) {
        GlobalScope.launch(CoroutineScopeManager.mainDispatcher) {
            handlerMusicState(MusicState.STOPING)
            currentMusicProgress = 0
            mediaPlayer?.stop()
            delay(300)
            success.invoke()
        }
    }

    /**
     * 播放进度控制
     */
    fun seekTo(progress: Long) {
        mediaPlayer?.seekTo(progress)
    }

    /**
     * 设置播放类型
     */
    private fun setMusicPlayType(@MusicPlayType type: Int) {
        playType = type
        handlerMusicPlayType(playType)
        mediaPlayer?.enableRepeat(playType == MusicPlay.MUSIC_SINGLE)
    }

    /**
     * 切换
     */
    fun chickMusicPlayType() {
        val type = when (playType) {
            MusicPlay.MUSIC_SINGLE -> {
                ToastGravity.showGravity(StringUtils.getString(R.string.shuffle))
                MusicPlay.MUSIC_RANDOM

            }

            MusicPlay.MUSIC_RANDOM -> {
                ToastGravity.showGravity(StringUtils.getString(R.string.sequential_playback))
                MusicPlay.MUSIC_ORDER

            }

            MusicPlay.MUSIC_ORDER -> {
                ToastGravity.showGravity(StringUtils.getString(R.string.single_tune_circulation))
                MusicPlay.MUSIC_SINGLE

            }

            else -> MusicPlay.MUSIC_SINGLE
        }
        setMusicPlayType(type)
    }

    /**
     * 获取播放类型
     */
    fun getMusicPlayType(): Int {
        return playType
    }

    /**
     * 获取播放状态
     */
    fun getCurrentMusicState(): Int {
        return currentMusicState
    }

    /**
     * 获取播放进度
     */
    fun getCurrentMusicProgress(): Long {
        return currentMusicProgress
    }

    /**
     * 获取播放类
     */
    fun getCurrentMusicBean(): MusicBean? {
        return currentMusicBean
    }

    /**
     * 获取播放音量
     */
    fun getPlayVolume(): Int {
        return mediaPlayer?.getPlayVolume() ?: 0
    }

    /**
     * 控制播放音量
     */
    fun setPlayVolume(volume: Int) {
        handlerVolume(volume)
        mediaPlayer?.setPlayVolume(volume)
    }

    /**
     * 控制推流音量
     */
    fun setPublishVolume(volume: Int) {
        mediaPlayer?.setPublishVolume(volume)
    }

}

object MusicState {

    const val FAIL = -1                     //失败
    const val UNREADY = 0                   //未准备好
    const val READY = 1                   //准备好
    const val PLAYING = 2                   //播放中
    const val PAUSE = 3                   //暂停中
    const val STOPING = 4                   //停止
    const val PLAY_ENDED = 5                  //完毕
}

@IntDef(
    MusicState.UNREADY,
    MusicState.READY,
    MusicState.PLAYING,
    MusicState.STOPING,
    MusicState.PAUSE,
    MusicState.PLAY_ENDED,
    MusicState.FAIL,
)
annotation class MusicPlayState
object MusicPlay {

    const val MUSIC_ONE_SINGLE = 100001               //只播放一次
    const val MUSIC_SINGLE = 100002                   //单曲循环
    const val MUSIC_RANDOM = 100003                  //随机
    const val MUSIC_ORDER = 100004                  //顺序
}

@IntDef(
    MusicPlay.MUSIC_ONE_SINGLE,
    MusicPlay.MUSIC_SINGLE,
    MusicPlay.MUSIC_RANDOM,
    MusicPlay.MUSIC_ORDER
)
annotation class MusicPlayType